﻿using System.Linq;
using NJabber.Stream.Elements;
using NUnit.Framework;
using FakeItEasy;

namespace NJabber.Client.StanzaFactories
{
    [TestFixture]
    public class RosterStanzaFactoryTest
    {
        [Test]
        public void CreateRosterRequest__CreatesCorrectStanza()
        {
            RosterStanzaFactory factory = new RosterStanzaFactory();
            JID senderJid = "some-jid@domain.com";

            IqStanza rosterRequest = factory.CreateRosterRequest(senderJid) as IqStanza;

            VerifyRosterRequestStanza(rosterRequest, senderJid);
        }

        private void VerifyRosterRequestStanza(IqStanza rosterRequest, JID senderJid)
        {
            AssertRosterStanza(rosterRequest, senderJid, IqStanzaTypes.Get);
            IqQueryElement query = rosterRequest.GetQueryElement();
            Assert.That(query.Content, Is.Empty);
        }

        [Test]
        public void CreateAddItemRequest__CreatesCorrectStanza()
        {
            RosterStanzaFactory factory = new RosterStanzaFactory();
            RosterItem item = new RosterItem("new-item", "new-item@jid.com");
            JID senderId = "some-jid@domain.com";

            IqStanza addItemReqest = factory.CreateAddRosterItemRequest(item, senderId) as IqStanza;

            VerifyAddOrUpdateItemRequest(addItemReqest, senderId, item);
        }

        [Test]
        public void CreateUpdateRosterItemRequest__CreatesCorrectStanza()
        {
            RosterStanzaFactory factory = new RosterStanzaFactory();
            RosterItem updatedItem = new RosterItem("updated-item", "updated-item@jid.com");
            JID senderId = "sender@jid.com";

            IqStanza stanza = factory.CreateUpdateRosterItemRequest(A.Dummy<RosterItem>(), updatedItem, senderId) as IqStanza;

            VerifyAddOrUpdateItemRequest(stanza, senderId, updatedItem);
        }

        private void VerifyAddOrUpdateItemRequest(IqStanza addItemReqest, JID senderId, RosterItem item)
        {
            AssertRosterStanza(addItemReqest, senderId, IqStanzaTypes.Set);
            RosterItem item2 = addItemReqest.GetRosterItemsElements().Single();
            Assert.That(item2, Is.EqualTo(item));
        }

        [Test]
        public void CreateDeleteRosterItemRequest__CreatesCorrectStanza()
        {
            RosterStanzaFactory factory = new RosterStanzaFactory();
            RosterItem deleteItem = new RosterItem("delete-item", "delete-item@jid.com");
            JID senderId = "some-jid@domain.com";

            IqStanza stanza = factory.CreateDeleteRosterItemRequest(deleteItem, senderId) as IqStanza;

            VerifyDeleteItemRequest(stanza, senderId, deleteItem);
        }

        private void VerifyDeleteItemRequest(IqStanza stanza, JID senderId, RosterItem deleteItem)
        {
            AssertRosterStanza(stanza, senderId, IqStanzaTypes.Set);
            RosterItemElement rosterItem = stanza.GetRosterItemsElements().Single();
            Assert.That(rosterItem.Jid, Is.EqualTo(deleteItem.Jid));
            Assert.That(rosterItem.Subscription, Is.EqualTo("remove"));
        }

        private void AssertRosterStanza(IqStanza stanza, JID senderJid, string stanzaType)
        {
            Assert.That(stanza.HasRosterQuery(), Is.True);
            Assert.That(stanza.From, Is.EqualTo(senderJid));
            Assert.That(stanza.Type, Is.EqualTo(stanzaType));
        }
    }
}
